#include<stdlib.h>
#include<unistd.h>
#include<netinet/in.h>
#include<sys/socket.h>
#include<sys/epoll.h>
#include<string.h>
#include<sys/msg.h>
#include<stdio.h>
#include<time.h>

#define PORT 9400
#define EPOLL_SIZE 20
#define BUFSIZE 512
#define MSG 1024

struct t_data{
	time_t t_in;
	int fd;
};

struct Mmsg{
	long mtype;
	char trid[6];
	char id[20];
	char pwd[4];
	char padding[994];
};

struct Mmsg2{
	long mtype;
	char trid[6];
	char id[20];
	char branch[20];
	char padding[978];
};

char** parsing(char*, char*);

int main(){
	struct sockaddr_in addr, clientaddr;
	struct epoll_event ev, *events;
	struct t_data *udata, *p;
	int listenfd;
	int clientfd;
	int i;
	socklen_t addrlen, clilen;
	int readn;
	int eventn;
	int epollfd;
	char buf[MSG];
	time_t t;
	int optval=1;
	char dev[]=" ,\t\n";
	char **par;
	//
	key_t key;
	int msgid;
	struct Mmsg mmsg1;
	struct Mmsg2 mmsg2;
	int len;

//mque
	key=ftok("key", 3000);
	msgid=msgget(key,IPC_CREAT|0644);
	if(msgid==-1){
		perror("msgget");
		exit(1);
	}
	
//epoll
	events = (struct epoll_event*)malloc(sizeof(struct epoll_event)*EPOLL_SIZE);

	if((epollfd=epoll_create(100))==-1){
		perror("epollfd");
		exit(1);
	}

	addrlen=sizeof(addr);
	if((listenfd=socket(AF_INET,SOCK_STREAM,0))==-1){
		perror("listenfd");
		exit(1);
	}

	setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&optval,sizeof(optval));
	addr.sin_family=AF_INET;
	addr.sin_port=htons(PORT);
	addr.sin_addr.s_addr=htonl(INADDR_ANY);
	if(bind(listenfd,(struct sockaddr *)&addr, addrlen)==-1){
		perror("bind");
		exit(1);
	}
	listen(listenfd,5);

	ev.events=EPOLLIN;
	ev.data.fd=listenfd;
	epoll_ctl(epollfd,EPOLL_CTL_ADD,listenfd,&ev);

	while(1){
		eventn=epoll_wait(epollfd,events,EPOLL_SIZE,-1);
		if(eventn==-1){
			perror("epoll_wait");
			exit(1);
		}
		for(i=0;i<eventn;i++){
			if(events[i].data.fd==listenfd){
				clilen=sizeof(struct sockaddr);
				clientfd=accept(listenfd,(struct sockaddr*)&clientaddr,&clilen);
				if(clientfd<0){
					perror("accept");
					exit(1);
				}

				udata=(struct t_data*)malloc(sizeof(struct t_data));
				memset(udata,0x00,sizeof(struct t_data));

				time(&t);
				udata->t_in=t;
				udata->fd=clientfd;
				ev.data.ptr=(void*)udata;
				ev.events=EPOLLIN;
				
				epoll_ctl(epollfd,EPOLL_CTL_ADD,clientfd,&ev);
			}
			else
			{
				p=(struct t_data*)events[i].data.ptr;
				memset(buf,0x00,MSG);
				readn=read(p->fd,buf,MSG);
				if(readn<=0){
					epoll_ctl(epollfd,EPOLL_CTL_DEL,p->fd,events);
					close(p->fd);
					free(p);
				}
				else
				{
						printf("msgrcv from client: %s \n", buf);
					if(!strncmp(buf,"3008",4)){
						memset(&mmsg1,0x00,sizeof(mmsg1));
						par=parsing(buf,dev);
						strncpy(mmsg1.trid,par[0],6);
						strncpy(mmsg1.id,par[1],20);
						strncpy(mmsg1.pwd,par[2],4);
							
						mmsg1.mtype=1;
						if(msgsnd(msgid,&mmsg1,MSG,IPC_NOWAIT)==-1){
							perror("msgsnd");
							exit(1);
						}

						memset(&mmsg2,0x00,sizeof(mmsg2));

						mmsg2.mtype=2;
						if((len=msgrcv(msgid,&mmsg2,MSG,2,0))>0){
							memset(buf,0x00,MSG);
							strncpy(buf,mmsg2.trid,6);
							strncat(buf,mmsg2.id,20);
							strncat(&buf,mmsg2.branch,20);
							write(p->fd,buf,MSG);
						}
						printf("msgrcv from bp: %s \n", buf);
					}
				}
			}
		}
	}
	return 0;
}

char** parsing(char* buf, char* dev){
	char **send;
	char *token;
	int i=0;

	send=(char**)malloc(strlen(buf));
	memset(send,0x00,sizeof(send));
	token=strtok(buf,dev);
	while(token!=NULL){
		send[i]=token;
		token=strtok(NULL,dev);
		i++;
	}
	send[i]=NULL;
	return send;
}


